package com.meilai.project.service.business.sale.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.dto.business.sale.BillSaleGroupDTO;
import com.meilai.project.dto.business.saleOrder.SaleQueryGroupDTO;
import com.meilai.project.entity.business.sale.BillSale;
import com.meilai.project.entity.business.sale.BillSaleGroup;
import com.meilai.project.entity.business.sale.BillSaleGroupRelation;
import com.meilai.project.entity.finance.paymentReceived.AccountReceived;
import com.meilai.project.entity.finance.paymentReceived.AccountReceivedBillSaleRelation;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.business.sale.BillSaleGroupMapper;
import com.meilai.project.mapper.business.sale.BillSaleMapper;
import com.meilai.project.service.business.sale.BillSaleGroupRelationService;
import com.meilai.project.service.business.sale.BillSaleGroupService;
import com.meilai.project.service.finance.paymentReceived.AccountReceivedBillSaleRelationService;
import com.meilai.project.service.finance.paymentReceived.AccountReceivedService;
import com.meilai.project.util.ThreadLocalUserUtil;
import com.meilai.project.vo.business.sale.BillSaleGroupRelationIdsVO;
import com.meilai.project.vo.business.sale.BillSaleGroupVO;
import com.meilai.project.vo.business.sale.BillSaleVO;
import com.meilai.project.vo.business.sale.ContractCustomerVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 销售分组表 服务实现类
 * </p>
 *
 * @author xhy
 * @since 2022-12-05
 */
@Service
public class BillSaleGroupServiceImpl extends ServiceImpl<BillSaleGroupMapper, BillSaleGroup> implements BillSaleGroupService {

    @Autowired
    private BillSaleMapper billSaleMapper;

    @Autowired
    private BillSaleGroupRelationService billSaleGroupRelationService;

    @Autowired
    private AccountReceivedService accountReceivedService;

    @Autowired
    private AccountReceivedBillSaleRelationService accountReceivedBillSaleRelationService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean relation(BillSaleGroupDTO dto) {
        if (dto.getType() == null || (dto.getType() != 1 && dto.getType() != 2)) {
            throw new CommonException("提交的数据异常，请联系管理员");
        }
        if (dto.getAccount_received_id() == null && dto.getEdit_group_id() == null) {
            throw new CommonException("提交的数据异常，请联系管理员");
        }
        if (dto.getEdit_group_id() != null && CollectionUtils.isEmpty(dto.getBill_sale_ids())){
            throw new CommonException("提交的数据异常，请联系管理员");
        }
        if(dto.getType() == 2 && dto.getEdit_group_id() != null){
            // 编辑分组
            if (CollectionUtils.isEmpty(dto.getBill_sale_ids()) || StringUtils.isEmpty(dto.getName())) {
                throw new CommonException("提交的数据异常，请联系管理员");
            }
            // 前置检查销售单是否来源于同一个合同
            List<BillSale> billSales = billSaleMapper.selectList(Wrappers.<BillSale>lambdaQuery().in(BillSale::getId, dto.getBill_sale_ids()));
            if (billSales.stream().map(BillSale::getContract_id).collect(Collectors.toSet()).size() > 1) {
                throw new CommonException("所选销售单中不是同一个合同，请检查提交的销售单数据");
            }
            update(Wrappers.<BillSaleGroup>lambdaUpdate()
                    .set(BillSaleGroup::getName, dto.getName())
                    .eq(BillSaleGroup::getId, dto.getEdit_group_id()));
            billSaleGroupRelationService.remove(Wrappers.<BillSaleGroupRelation>lambdaQuery().eq(BillSaleGroupRelation::getGroup_id, dto.getEdit_group_id()));
            List<BillSaleGroupRelation> billSaleGroupRelationList = dto.getBill_sale_ids().stream().map(item -> {
                BillSaleGroupRelation relation = new BillSaleGroupRelation();
                relation.setBill_sale_id(item);
                relation.setGroup_id(dto.getEdit_group_id());
                return relation;
            }).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(billSaleGroupRelationList)) billSaleGroupRelationService.saveBatch(billSaleGroupRelationList);
            return true;
        } else if (dto.getType() == 2 && dto.getEdit_group_id() == null) {
            // 如果是新建分组
            if (CollectionUtils.isEmpty(dto.getBill_sale_ids()) || StringUtils.isEmpty(dto.getName())) {
                throw new CommonException("提交的数据异常，请联系管理员");
            } else {
                // 前置检查销售单是否来源于同一个合同
                List<BillSale> billSales = billSaleMapper.selectList(Wrappers.<BillSale>lambdaQuery().in(BillSale::getId, dto.getBill_sale_ids()));
                if (billSales.stream().map(BillSale::getContract_id).collect(Collectors.toSet()).size() > 1) {
                    throw new CommonException("所选销售单中不是同一个合同，请检查提交的销售单数据");
                }
                BillSaleGroup group = new BillSaleGroup();
                group.setCreated_by(ThreadLocalUserUtil.get().getId());
                group.setName(dto.getName());
                group.setCreated_at(LocalDateTime.now());
                this.save(group);
                List<BillSaleGroupRelation> billSaleGroupRelationList = new ArrayList<>();
                List<AccountReceivedBillSaleRelation> accountReceivedBillSaleRelationList = new ArrayList<>();
                dto.getBill_sale_ids().forEach(item -> {
                    BillSaleGroupRelation relation = new BillSaleGroupRelation();
                    relation.setBill_sale_id(item);
                    relation.setGroup_id(group.getId());
                    billSaleGroupRelationList.add(relation);
                    AccountReceivedBillSaleRelation accountReceivedBillSaleRelation = new AccountReceivedBillSaleRelation();
                    accountReceivedBillSaleRelation.setAccount_received_id(dto.getAccount_received_id());
                    accountReceivedBillSaleRelation.setBill_sale_id(item);
                    accountReceivedBillSaleRelationList.add(accountReceivedBillSaleRelation);
                });
                billSaleGroupRelationService.saveBatch(billSaleGroupRelationList);
                //  将款项关联到对应的组
                accountReceivedService.update(Wrappers.<AccountReceived>lambdaUpdate().set(AccountReceived::getGroup_id, group.getId()).eq(AccountReceived::getId, dto.getAccount_received_id()));
                accountReceivedBillSaleRelationService.saveBatch(accountReceivedBillSaleRelationList);
                return true;
            }
        } else {
            // 已经有的分组
            if (dto.getGroup_id() == null) {
                throw new CommonException("提交的数据异常，请联系管理员");
            } else {
                //  将款项关联到对应的组
                accountReceivedService.update(Wrappers.<AccountReceived>lambdaUpdate().set(AccountReceived::getGroup_id, dto.getGroup_id()).eq(AccountReceived::getId, dto.getAccount_received_id()));
                List<BillSaleGroupRelation> list = billSaleGroupRelationService.list(Wrappers.<BillSaleGroupRelation>lambdaQuery().eq(BillSaleGroupRelation::getGroup_id, dto.getAccount_received_id()));
                accountReceivedBillSaleRelationService.saveBatch(list.stream().map(item -> {
                    AccountReceivedBillSaleRelation tmp = new AccountReceivedBillSaleRelation();
                    tmp.setBill_sale_id(item.getBill_sale_id());
                    tmp.setAccount_received_id(dto.getAccount_received_id());
                    return tmp;
                }).collect(Collectors.toList()));
                return true;
            }
        }
    }

    @Override
    public List<BillSaleVO> saleList(Long customer_id) {
        return baseMapper.seleList(null, customer_id, null);
    }

    @Override
    public List<BillSaleVO> saleListInGroup(Long group_id) {
        return baseMapper.seleList(null, null, group_id);
    }

    @Override
    public List<BillSaleGroupVO> selectList() {
        List<BillSaleGroup> list = this.list(Wrappers.<BillSaleGroup>lambdaQuery().eq(BillSaleGroup::getCreated_by, ThreadLocalUserUtil.get().getId()).orderByDesc(BillSaleGroup::getCreated_at));
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        } else {
            List<Long> group_ids = list.stream().map(BillSaleGroup::getId).collect(Collectors.toList());
            List<BillSaleGroupRelation> relationList = billSaleGroupRelationService.list(Wrappers.<BillSaleGroupRelation>lambdaQuery().in(BillSaleGroupRelation::getGroup_id, group_ids));
            Map<Long, List<Long>> group_map = relationList.stream().collect(Collectors.groupingBy(BillSaleGroupRelation::getGroup_id, Collectors.mapping(BillSaleGroupRelation::getBill_sale_id, Collectors.toList())));
            List<Long> bill_sale_ids = relationList.stream().map(BillSaleGroupRelation::getBill_sale_id).collect(Collectors.toList());
            // 查询销售单数据
            List<BillSaleVO> billSaleVOS = billSaleMapper.selectListOfIds(bill_sale_ids);
            return list.stream().map(item -> {
                BillSaleGroupVO vo = new BillSaleGroupVO();
                BeanUtils.copyProperties(item, vo);
                List<Long> ids = group_map.get(vo.getId());
                if (CollectionUtils.isEmpty(ids)) {
                    vo.setSaleVOList(new ArrayList<>());
                } else {
                    List<BillSaleVO> collect = billSaleVOS.stream().filter(tmp -> ids.contains(tmp.getId())).collect(Collectors.toList());
                    vo.setSaleVOList(collect);
                }
                return vo;
            }).collect(Collectors.toList());
        }
    }

    private List<BillSaleGroupVO> handleVOList(List<BillSaleGroupRelationIdsVO> idsVoList, SaleQueryGroupDTO dto){
        List<BillSaleGroupVO> result = new ArrayList<>();

        if(CollectionUtils.isNotEmpty(idsVoList)){
            LambdaQueryWrapper<BillSaleGroup> qw_group = Wrappers.<BillSaleGroup>lambdaQuery()
                    .in(BillSaleGroup::getId, idsVoList.stream().map(BillSaleGroupRelationIdsVO::getGroup_id).collect(Collectors.toSet()))
                    .orderByDesc(BillSaleGroup::getCreated_at);
            if(dto.getCreate_by()) qw_group.eq(BillSaleGroup::getCreated_by, ThreadLocalUserUtil.get().getId());
            List<BillSaleGroup> list = list(qw_group);

            Map<Long, Set<Long>> groupIdAndBillIds = idsVoList.stream().collect(
                    Collectors.groupingBy(BillSaleGroupRelationIdsVO::getGroup_id,
                            Collectors.mapping(BillSaleGroupRelationIdsVO::getBill_sale_id, Collectors.toSet())));

            if (CollectionUtils.isNotEmpty(list)){
                // 查询销售单数据
                List<BillSaleVO> billSaleVOS = billSaleMapper.selectListOfIds(idsVoList.stream().map(BillSaleGroupRelationIdsVO::getBill_sale_id).collect(Collectors.toList()));
                result = list.stream().map(item -> {
                    BillSaleGroupVO vo = new BillSaleGroupVO();
                    BeanUtils.copyProperties(item, vo);
                    Set<Long> billIds = groupIdAndBillIds.getOrDefault(item.getId(), new HashSet<>());
                    List<BillSaleVO> bills = billSaleVOS.stream().filter(tmp -> billIds.contains(tmp.getId())).collect(Collectors.toList());
                    vo.setSaleVOList(CollectionUtils.isNotEmpty(bills) ? bills: new ArrayList<>());
                    return vo;
                }).collect(Collectors.toList());
            }
        }
        return result;
    }

    @Override
    public List<BillSaleGroupVO> selectListByAccountReceivedId(Long accountReceivedId) {
        SaleQueryGroupDTO dto = SaleQueryGroupDTO.builder()
                .account_received_id(accountReceivedId)
                .build();
        return handleVOList(baseMapper.getGroupIdsByDto(dto), dto);
    }

    @Override
    public List<BillSaleGroupVO> selectListByDto(SaleQueryGroupDTO dto) {
        return handleVOList(baseMapper.getGroupIdsByDto(dto), dto);
    }

    @Override
    public ContractCustomerVO getContractAndCustomerByGroupId(Long group_id) {
        // 查询组别关联的销售单信息
        List<BillSaleGroupRelation> list = billSaleGroupRelationService.list(Wrappers.<BillSaleGroupRelation>lambdaQuery().eq(BillSaleGroupRelation::getGroup_id, group_id));
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> bill_sale_ids = list.stream().map(BillSaleGroupRelation::getBill_sale_id).collect(Collectors.toList());
            List<BillSaleVO> voList = billSaleMapper.selectListOfIds(bill_sale_ids);
            List<Long> contract_id = voList.stream().map(BillSaleVO::getContract_id).distinct().collect(Collectors.toList());
            if (contract_id.size() > 1) {
                throw new CommonException("组中销售单数据异常，请联系管理员");
            } else {
                ContractCustomerVO vo = baseMapper.getContractAndCustomerByGroupId(contract_id.get(0));
                if (vo == null) {
                    throw new CommonException("数据异常，请联系管理员");
                } else {
                    // 计算销售单执行总额
                    BigDecimal sum = new BigDecimal("0");
                    for (BillSaleVO billSaleVO : voList) {
                        // 修复赠送销售单执行金额为零的问题
                        if (billSaleVO.getExecute_amount() != null) {
                            sum = sum.add(billSaleVO.getExecute_amount());
                        }
                    }
                    vo.setAmount(sum);
                    return vo;
                }
            }
        } else {
            throw new CommonException("组中没有销售单信息，请联系管理员");
        }
    }

    @Override
    public Map<Long, ContractCustomerVO> getContractAndCustomerByGroupIds(List<Long> group_ids) {
        Map<Long, ContractCustomerVO> map = new HashMap<>();
        // 查询组别关联的销售单信息
        List<BillSaleGroupRelation> list = billSaleGroupRelationService.list(Wrappers.<BillSaleGroupRelation>lambdaQuery().in(BillSaleGroupRelation::getGroup_id, group_ids));
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> bill_sale_ids = list.stream().map(BillSaleGroupRelation::getBill_sale_id).collect(Collectors.toList());
            Map<Long, List<Long>> group_map = list.stream().collect(Collectors.groupingBy(BillSaleGroupRelation::getGroup_id, Collectors.mapping(BillSaleGroupRelation::getBill_sale_id, Collectors.toList())));
            List<BillSaleVO> voList = billSaleMapper.selectListOfIds(bill_sale_ids);
            Map<Long, BillSaleVO> bill_sale_map = voList.stream().collect(Collectors.toMap(BillSaleVO::getId, Function.identity()));
            List<Long> collect = voList.stream().map(BillSaleVO::getContract_id).distinct().collect(Collectors.toList());
            Map<Long, ContractCustomerVO> contractCustomerVOMap = baseMapper.getContractAndCustomerByGroupIds(collect).stream().collect(Collectors.toMap(ContractCustomerVO::getContract_id, Function.identity()));
            group_map.forEach((key, value) -> {
                for (Long id : value) {
                    BillSaleVO billSaleVO = bill_sale_map.get(id);
                    if (billSaleVO != null) {
                        ContractCustomerVO vo = contractCustomerVOMap.get(billSaleVO.getContract_id());
                        if (vo != null) {
                            map.put(key, vo);
                            break;
                        }
                    }
                }
            });
        } else {
            throw new CommonException("组中没有销售单信息，请联系管理员");
        }
        return map;
    }

    @Override
    public List<BillSaleGroup> listGroup(Long user_id) {
        return baseMapper.selectList(Wrappers.<BillSaleGroup>lambdaQuery().select(BillSaleGroup::getId,BillSaleGroup::getName).eq(BillSaleGroup::getCreated_by, user_id));
    }
}
